home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Plug-In Power Pack for Netscape Communicator
/
Plug-In Power Pack for Netscape Communicator.iso
/
plugins
/
dataviews
/
dvtools
/
demos
/
surfdemo
/
surfeqns.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-07-10
|
13KB
|
453 lines
#ifndef lint
static char SccsId[]= "@(#)surfeqns.c V1.4 3/19/92";
#endif
/*------------------------------------------------------------------
| file name -- surfeqns.c
|
| Functions associated with calculating the data from the formula
| equations.
|
| functions Description
| --------- -----------
| InitData Initializes the global data
| SetDefaults Sets the default parameters for the equation
| GenerateData Generates the data from the equation
|-----------------------------------------------------------------*/
#include <math.h>
#include "std.h"
#include "dvstd.h"
#include "dvtools.h"
#include "VOstd.h"
#include "surfdata.h"
#include "dvtoolfuns.h"
#include "dvinteract.h"
#include "VPfundecl.h"
#include "surffundecl.h"
#define SUM_OF 0
#define DIFFERENCE_OF 1
#define LOG_OF 2
#define SQRT_OF 3
#define TIMES_4 4
#define SIN_OF 5
#define EXPONENTIAL_OF 6
#define INITIAL_FORMULA SUM_OF
VOID SetThresholds ();
/*------------------------------------------------------------------
|
| InitData
| Initialize the global parameters associated with generating data
| from the formula equations.
*/
void InitData
V_P_ ((void))
{
/* Set up the initial plot information */
Plot.xdivisions = 30;
Plot.ydivisions = 30;
Plot.automaticz = YES;
Plot.inverted = 1.0;
Plot.context = NO;
Plot.format = SURFACE;
/* Set up the initial Formula information */
Formula.text = FormulaMenu[INITIAL_FORMULA];
Formula.pick = -1;
Formula.data = NULL;
SetDefaults (INITIAL_FORMULA, (DV_BOOL) NO);
/* Initialize the text strings for the text input handlers */
(VOID) S_SPRINTF (TextStr[XDIV_INPUT], "%d", Plot.xdivisions);
(VOID) S_SPRINTF (TextStr[YDIV_INPUT], "%d", Plot.ydivisions);
/* Set the last datagen information to the current */
LastGen.pick = Formula.pick;
LastGen.xmin = Formula.xmin;
LastGen.xmax = Formula.xmax;
LastGen.ymin = Formula.ymin;
LastGen.ymax = Formula.ymax;
LastGen.xdiv = Plot.xdivisions;
LastGen.ydiv = Plot.ydivisions;
LastGen.autoz = Plot.automaticz;
LastGen.zmin = Formula.zmin;
LastGen.zmax = Formula.zmax;
LastGen.invert = Plot.inverted;
}
/*------------------------------------------------------------------
|
| SetDefaults
| Initialize the default parameters associated with a particular
| equations.
*/
void
SetDefaults (pick, draw_text)
int pick;
BOOLPARAM draw_text;
{
FLOAT tempmax;
/* If there hasn't been a change, don't do anything */
if (pick == Formula.pick)
return;
/* Set the new index and assign the new default values */
Formula.pick = pick;
switch (pick)
{
case SUM_OF:
/* x^2 + y^2 */
Formula.xmin = -50.0;
Formula.xmax = 50.0;
Formula.ymin = -50.0;
Formula.ymax = 50.0;
Formula.zmin = 0.0;
Formula.zmax = 5000.0;
break;
case DIFFERENCE_OF:
/* x^2 - y^2 */
Formula.xmin = -25.0;
Formula.xmax = 25.0;
Formula.ymin = -25.0;
Formula.ymax = 25.0;
Formula.zmin = -625.0;
Formula.zmax = 625.0;
break;
case LOG_OF:
/* ln(|x| + |y| */
Formula.xmin = -2.0;
Formula.xmax = 2.0;
Formula.ymin = -2.0;
Formula.ymax = 2.0;
Formula.zmin = -1.5;
Formula.zmax = 1.5;
break;
case SQRT_OF:
/* sqrt(100 - x^2 - y^2) */
Formula.xmin = -12.5;
Formula.xmax = 12.5;
Formula.ymin = -12.5;
Formula.ymax = 12.5;
Formula.zmin = 0.0;
Formula.zmax = 10.0;
break;
case TIMES_4:
/* 4*x^3*y - 4*x*y^3 */
Formula.xmin = -0.5;
Formula.xmax = 0.5;
Formula.ymin = -0.5;
Formula.ymax = 0.5;
Formula.zmin = -0.1F;
Formula.zmax = 0.1F;
break;
case SIN_OF:
/* sin(pi * r) / (pi * r) */
Formula.xmin = -4.5;
Formula.xmax = 4.5;
Formula.ymin = -4.5;
Formula.ymax = 4.5;
Formula.zmin = -0.25;
Formula.zmax = 1.0;
break;
case EXPONENTIAL_OF:
/* (x^2 + 2*y^2) * e^(1-x^2-y^2) */
Formula.xmin = -2.5;
Formula.xmax = 2.5;
Formula.ymin = -2.5;
Formula.ymax = 2.5;
Formula.zmin = 0.0;
Formula.zmax = 2.0;
break;
}
if (Plot.inverted == -1.0)
{
tempmax = Formula.zmax;
Formula.zmax = Formula.zmin * -1.0F;
Formula.zmin = tempmax * -1.0F;
}
/* Compute the new actual threshold value */
SetThresholds ();
/* Set up the text variables for the data limit input objects */
(VOID) S_SPRINTF (TextStr[XMIN_INPUT], "%.6g", Formula.xmin);
(VOID) S_SPRINTF (TextStr[XMAX_INPUT], "%.6g", Formula.xmax);
(VOID) S_SPRINTF (TextStr[YMIN_INPUT], "%.6g", Formula.ymin);
(VOID) S_SPRINTF (TextStr[YMAX_INPUT], "%.6g", Formula.ymax);
(VOID) S_SPRINTF (TextStr[ZMIN_INPUT], "%.6g", Formula.zmin);
(VOID) S_SPRINTF (TextStr[ZMAX_INPUT], "%.6g", Formula.zmax);
if (draw_text)
{
/* Change the formula text object to display the new formula */
PrintMessage (FormulaMenu[pick], YES);
/* Redraw each of the user scaled input objects */
ReDrawTextInputs ();
}
}
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/*------------------------------------------------------------------
|
| GenerateData
| Generates the data associated with the current equation.
*/
void
GenerateData (firsttime)
int firsttime;
{
FLOAT x, y; /* Actual x and y values */
FLOAT tmp; /* Temporary for optimizing */
FLOAT tmp2; /* Temporary for optimizing */
FLOAT minx, miny, maxx, maxy; /* Min and max range values */
FLOAT deltax, deltay; /* Used to step through range */
INT countx, county; /* Num divisions in each range */
INT timinginc; /* For updating timing dial */
FLOAT result; /* Result of the computation */
FLOAT *dataptr; /* Pointer to the data area */
FLOAT mindata, maxdata; /* Min and max result for this run */
/* Free the old data area and get a new one of the correct size */
if (Formula.data)
S_FREE ((ADDRESS) Formula.data);
Formula.data = (FLOAT *) S_ALLOC ((LONG) (sizeof (FLOAT) *
Plot.xdivisions * Plot.ydivisions));
/* Tell the graph where to find the data */
(VOID) TvdPutBuffer (GraphVdp, (ADDRESS) Formula.data);
/* Set the dimentions of the plot */
VPvddim (GraphVdp, 1, Plot.ydivisions, Plot.xdivisions);
/* Set the timing increment to do 100 updates */
timinginc = (Plot.xdivisions * Plot.ydivisions) / 50;
if (timinginc == 0)
timinginc = 1;
/* Set the data limits and compute the increment values */
minx = Formula.xmin;
maxx = Formula.xmax;
miny = Formula.ymin;
maxy = Formula.ymax;
deltax = (maxx - minx) / (Plot.xdivisions - 1);
deltay = (maxy - miny) / (Plot.ydivisions - 1);
/* Get the pointer to the beginning of the data area */
dataptr = Formula.data;
/* Set dummy min and max values */
mindata = 1.0e30F;
maxdata = -1.0e30F;
y = miny;
for (county = 0; county < Plot.ydivisions; county++)
{
x = minx;
for (countx = 0; countx < Plot.xdivisions; countx++)
{
/* For each data point, apply the correct function */
switch (Formula.pick)
{
case SUM_OF:
result = x * x + y * y;
break;
case DIFFERENCE_OF:
result = (x * x - y * y);
break;
case LOG_OF:
tmp = (FLOAT)(fabs (x) + fabs (y));
/* Avoid the discontinuity around ln(0) */
if (tmp != 0)
result = (FLOAT)log (tmp);
else
result = Formula.zmin;
break;
case SQRT_OF:
if (100 - x * x - y * y >= 0.0)
result = (FLOAT)sqrt (100 - x * x - y * y);
/* Don't try to take sqrt of a negative */
else
result = 0.0;
break;
case TIMES_4:
result = 4 * x * x * x * y - 4 * x * y * y * y;
break;
case SIN_OF:
tmp = (FLOAT)sqrt (x * x + y * y);
/* Don't divide by zero */
if (tmp == 0)
result = 1.0;
else
result = (FLOAT)(sin (M_PI * tmp) / (M_PI * tmp));
break;
case EXPONENTIAL_OF:
tmp = x * x;
tmp2 = y * y;
result = (tmp + (tmp2 + tmp2)) * (FLOAT)exp (1 - tmp - tmp2);
break;
}
/* Invert this point if necessary */
result *= Plot.inverted;
/* Keep track of the minimum and maximum values */
if (result < mindata)
mindata = result;
if (result > maxdata)
maxdata = result;
/* Advance the data pointer */
*(dataptr)++ = result;
/* Update the "waiting" meter every "timinginc"-th data point */
TimingValue += 1.0;
if ((!firsttime) && (!((INT) TimingValue % timinginc)))
(VOID) TdpDrawNextObject (MainDrawport, TimingObj);
x += deltax;
}
y += deltay;
}
/* If we're auto scaling, set the range to the local min and max */
if (Plot.automaticz == YES)
{
VPvd_drange (GraphVdp, mindata, maxdata);
Formula.zmin = mindata;
Formula.zmax = maxdata;
SetThresholds ();
(VOID) S_SPRINTF (TextStr[ZMIN_INPUT], "%.6g", Formula.zmin);
(VOID) S_SPRINTF (TextStr[ZMAX_INPUT], "%.6g", Formula.zmax);
}
/* Else, set the range to be the range defined by the user */
else
VPvd_drange (GraphVdp, (DOUBLE) Formula.zmin, (DOUBLE) Formula.zmax);
}
/*------------------------------------------------------------------
|
| NeedToGenData
| Determines if we need to generate new data.
*/
BOOLPARAM NeedToGenData
V_P_ ((void))
{
DV_BOOL gen;
gen = NO;
if (LastGen.pick != Formula.pick)
gen = YES;
if (LastGen.xdiv != Plot.xdivisions)
gen = YES;
if (LastGen.ydiv != Plot.ydivisions)
gen = YES;
if (LastGen.xmin != Formula.xmin)
gen = YES;
if (LastGen.xmax != Formula.xmax)
gen = YES;
if (LastGen.ymin != Formula.ymin)
gen = YES;
if (LastGen.ymax != Formula.ymax)
gen = YES;
if (LastGen.autoz != Plot.automaticz)
gen = YES;
else if (LastGen.autoz == NO)
{
if (LastGen.zmin != Formula.zmin)
gen = YES;
if (LastGen.zmax != Formula.zmax)
gen = YES;
}
if (LastGen.invert != Plot.inverted)
gen = YES;
if (gen == NO)
return NO;
LastGen.pick = Formula.pick;
LastGen.xmin = Formula.xmin;
LastGen.xmax = Formula.xmax;
LastGen.ymin = Formula.ymin;
LastGen.ymax = Formula.ymax;
LastGen.zmin = Formula.zmin;
LastGen.zmax = Formula.zmax;
LastGen.xdiv = Plot.xdivisions;
LastGen.ydiv = Plot.ydivisions;
LastGen.autoz = Plot.automaticz;
LastGen.invert = Plot.inverted;
return YES;
}
/*------------------------------------------------------------------
|
| CheckPlotData
| Error messages assocated with checking the parameters.
*/
BOOLPARAM CheckPlotData
V_P_ ((void))
{
if (FormulaMenuActive || ThreshActive)
return NO;
if (!AreInputValuesValid ())
{
(VOID) S_PRINTF ("\007");
(VOID) S_FLUSHCHAR;
PrintMessage ("Invalid Range or no. of Divisions", NO);
return NO;
}
if (Formula.xmax <= Formula.xmin)
{
(VOID) S_PRINTF ("\007");
(VOID) S_FLUSHCHAR;
PrintMessage ("X Max must be > X Min", NO);
return NO;
}
if (Formula.ymax <= Formula.ymin)
{
(VOID) S_PRINTF ("\007");
(VOID) S_FLUSHCHAR;
PrintMessage ("Y Max must be > Y Min", NO);
return NO;
}
if (Formula.zmax <= Formula.zmin)
{
if (Plot.automaticz == NO)
{
(VOID) S_PRINTF ("\007");
(VOID) S_FLUSHCHAR;
PrintMessage ("Z Max must be > Z Min", NO);
return NO;
}
}
return YES;
}
void SetThresholds
V_P_ ((void))
{
INT i;
for (i = 0; i < NUM_THRESHOLDS; i++)
ThreshValue[i] = Formula.zmin + (ThreshTable[i].upperlimit / (FLOAT) 32768) *
(Formula.zmax - Formula.zmin);
}